/**
 * 状态模式：允许一个对象在其内部状态改变时改变它的行为，对象看起来似乎改变类它的类
 * 
 * 主要解决：当控制一个对象状态的条件表达式过于复杂时的情况，把状态的判断转移到表示不同状态到一系列类中，可以把复杂到判断逻辑简化。
 * 
 * 策略模式与状态模式相似：都是封装行为，通过委托来实现行为分发。
 * 
 * 与策略模式的区别：策略模式的行为函数，是对于逻辑的封装，彼此独立，不依赖调用主体，而状态模式中的行为函数，是和状态主体之间存在着直接的管理，
 */

 // 一个咖啡机生产四种咖啡的工序实现
 // 原始代码
class CoffeeMarker {
    constructor() {
        // 选择制作的咖啡类型
        this.state = 'init';
    }

    changeState(state) {
        this.state = state;
        if (state === 'american') {
            // 美式咖啡
            console.log('只吐黑咖啡')
        }else if (state === 'latte') {
            // 普通拿铁
            console.log('给黑咖啡加点奶')
        }else if (state === 'vanillaLatte') {
            // 香菜拿铁
            console.log('黑咖啡加点奶再加香草糖浆')
        }else if (state === 'mocha') {
            console.log('黑咖啡加点奶再加点巧克力')
        }
    }
}
const mk = new CoffeeMarker();
mk.changeState('latte')

// 改造
// 职责分离
class CoffeeMarker1 {
    constructor() {
        this.state = 'init'
    }

    changeState(state) {
        this.state = state;
        if (state === 'american') {
            // 美式咖啡
            this.american();
        }else if (state === 'latte') {
            // 普通拿铁
            this.latte();
        }else if (state === 'vanillaLatte') {
            // 香菜拿铁
            this.vanillaLattez();
        }else if (state === 'mocha') {
            this.mocha();
        }
    }

    american(){
        console.log('只吐黑咖啡')
    }

    latte() {
        this.american();
        console.log('加点奶');
    }

    vanillaLattez() {
        this.latte();
        console.log('加香草糖浆')
    }
    mocha() {
        this.latte();
        console.log('再加点巧克力')
    }
}

// 开放封闭，解决if-else
// 但使用这种方案，stateToProcessor感知不到咖啡机内的状况，比如还有木有奶，各种物料是否满足制作的要求
const stateToProcessor = {
    american(){
        console.log('只吐黑咖啡')
    },
    latte() {
        this.american();
        console.log('加点奶');
    },
    vanillaLattez() {
        this.latte();
        console.log('加香草糖浆')
    },
    mocha() {
        this.latte();
        console.log('再加点巧克力')
    },
}
class CoffeeMarker2 {
    constructor(){
        this.state = 'init';
    }
    changeState(state) {
        this.state = state;
        if (stateToProcessor[state]) {
            return;
        }
        stateToProcessor[state]();
    }
}

// 使用状态模式
class CoffeeMarker3 {
    constructor() {
        this.state = 'init';
        //咖啡机的其他状态变量
        this.leftMilk = '500ml'
    }
    // 将对象映射放入到类中，便于访问到咖啡机的状态，用于一些判断
    stateToProcessor = {
        that:this,
        american(){
            console.log('目前牛奶存储量', this.that.leftMilk)
            console.log('只吐黑咖啡')
        },
        latte() {
            this.american();
            console.log('加点奶');
        },
        vanillaLattez() {
            this.latte();
            console.log('加香草糖浆')
        },
        mocha() {
            this.latte();
            console.log('再加点巧克力')
        },
    }
    changeState(state) {
        this.state = state;
        if (this.stateToProcessor[state]) {
            return;
        }
        this.stateToProcessor[state]();
    }
}